package com.zatech.cgnci.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zatech.cgnci.project.base.context.UserContext;
import com.zatech.cgnci.project.base.enums.ClaimFlowEnum;
import com.zatech.cgnci.project.base.enums.ResponseCodeEnum;
import com.zatech.cgnci.project.base.enums.YesOrNoEnum;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.utils.ConvertUtils;
import com.zatech.cgnci.project.base.utils.VerifyUtils;
import com.zatech.cgnci.project.dto.CgnciClaimCaseAddDTO;
import com.zatech.cgnci.project.dto.CgnciClaimCaseQueryDTO;
import com.zatech.cgnci.project.entity.*;
import com.zatech.cgnci.project.mapper.CgnciApprovalInfoMapper;
import com.zatech.cgnci.project.mapper.CgnciApprovalRecordMapper;
import com.zatech.cgnci.project.mapper.CgnciBusinessInsuranceMapper;
import com.zatech.cgnci.project.mapper.CgnciClaimCaseMapper;
import com.zatech.cgnci.project.mapper.CgnciClaimCaseTaskMapper;
import com.zatech.cgnci.project.mapper.CgnciClaimPolicyMapper;
import com.zatech.cgnci.project.service.*;
import com.zatech.cgnci.project.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CgnciClaimCaseServiceImpl extends ServiceImpl<CgnciClaimCaseMapper, CgnciClaimCaseDO> implements CgnciClaimCaseService {
    @Resource
    private CgnciCodeTypeService cgnciCodeTypeService;
    @Autowired
    private CgnciClaimReserveService claimReserveService;
    @Resource
    private IApprovalService approvalService;
    @Resource
    private CgnciApprovalInfoMapper approvalInfoMapper;
    @Resource
    private CgnciApprovalRecordMapper approvalRecordMapper;
    @Resource
    private CgnciBusinessInsuranceService policyService;
    @Resource
    private CgnciAccessoryService accessoryService;
    @Resource
    private CgnciClaimAlertInfoService claimAlertInfoService;
    @Resource
    private CgnciClaimPolicyMapper claimPolicyMapper;
    @Resource
    private CgnciBusinessInsuranceMapper cgnciBusinessInsuranceMapper;
    @Resource
    private CgnciClaimReopenService reopenService;
    @Resource
    private CgnciClaimSettlementService claimSettlementService;
    @Resource
    private CgnciClaimCaseTaskMapper claimCaseTaskMapper;

//    @Resource
//    private CgnciClaimSettlementMapper claimSettlementMapper;

    @Override
    public IPage<CgnciClaimCasePageVO> pageClaimCase(CgnciClaimCaseQueryDTO queryDTO) {
        return this.baseMapper.pageClaimCase(queryDTO.toPage(), queryDTO);
    }

    @Override
    public CgnciClaimCaseVO detail(String caseNo) {
        // 基本信息
        CgnciClaimCaseDO claimCaseDO = getCaseByCaseNo(caseNo);
        Assert.notNull(claimCaseDO, "查询不到立案数据");
        CgnciClaimCaseVO claimCaseVO = ConvertUtils.convert(claimCaseDO, CgnciClaimCaseVO.class);
        // 获取关联保单信息
        CgnciClaimPolicyDO claimPolicy = claimPolicyMapper.selectOne(
                new LambdaQueryWrapper<CgnciClaimPolicyDO>()
                        .eq(CgnciClaimPolicyDO::getCaseNo, caseNo)
        );

        claimCaseVO.setClaimPolicy(ConvertUtils.convert(claimPolicy, CgnciClaimPolicyVO.class));
        // 获取附件信息
        List<CgnciAccessoryDO> accessoryList = accessoryService.list(new LambdaQueryWrapper<CgnciAccessoryDO>()
                .eq(CgnciAccessoryDO::getBusinessNo, caseNo)
                .eq(CgnciAccessoryDO::getUploadNode, ClaimFlowEnum.CLAIM_CASE.getCode()));
        claimCaseVO.setAccessoryList(ConvertUtils.convert(accessoryList, CgnciAccessoryVO.class));
        claimCaseVO.setSettlements(claimSettlementService.queryClaimSettlementByCaseNo(caseNo));
        claimCaseVO.setReserveVO(claimReserveService.detail(caseNo));
        claimCaseVO.setClaimReopen(ConvertUtils.convert(reopenService.getBaseMapper().selectOne(new LambdaQueryWrapper<CgnciClaimReopenDO>().eq(CgnciClaimReopenDO::getCaseNo,caseNo)),ClaimReopenVO.class));
        return claimCaseVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void synSaveClaimCase(CgnciClaimCaseAddDTO req) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        CgnciClaimCaseDO caseDO = getBaseMapper().selectOne(
                new LambdaQueryWrapper<CgnciClaimCaseDO>().eq(CgnciClaimCaseDO::getCaseNo, req.getCaseNo()));
        Assert.notNull(caseDO, StringUtils.join(req.getTaskNo(), "案件任务不存#synSaveClaimCase"));
        CgnciClaimCaseDO updateCease = new CgnciClaimCaseDO();
        BeanUtils.copyProperties(req, updateCease);
        updateCease.setCaseId(caseDO.getCaseId());
        updateById(updateCease);
        saveCasePolicyInfo(user, req);
        saveAttachment(user, req, caseDO.getCaseId());
    }

    private void saveCasePolicyInfo(UserEntity user, CgnciClaimCaseAddDTO req) {
        String caseNo = req.getCaseNo();
        CgnciClaimPolicyDO claimPolicyDO = claimPolicyMapper.selectOne(
                new LambdaQueryWrapper<CgnciClaimPolicyDO>()
                        .eq(CgnciClaimPolicyDO::getCaseNo, caseNo));
        CgnciBusinessInsuranceMainVO policyInfo = policyService.getPolicyInfo(req.getPolicyNo());
        if (Objects.isNull(policyInfo) || Objects.isNull(policyInfo.getBusinessInsuranceVO())) {
            log.info("{}保单不存在", req.getPolicyNo());
            return;
        }
        CgnciClaimPolicyDO claimPolicy = new CgnciClaimPolicyDO();
        CgnciBusinessInsuranceVO bizInsuranceVO = policyInfo.getBusinessInsuranceVO();
        claimPolicy.setCurrentPolicyId(bizInsuranceVO.getInsuranceId());
        claimPolicy.setCaseNo(caseNo);
        claimPolicy.setPolicyNo(req.getPolicyNo());
        claimPolicy.setRiskSubType(bizInsuranceVO.getRiskSubType());
        claimPolicy.setRiskSubTypeCode(bizInsuranceVO.getRiskSubTypeCode());
        claimPolicy.setProjectName(bizInsuranceVO.getProjectName());
        claimPolicy.setProjectNo(bizInsuranceVO.getProjectNo());
        claimPolicy.setCedingCompany(policyInfo.getReinsurers());
        claimPolicy.setAcceptCompany(policyInfo.getAcceptCompany());
        if (VerifyUtils.isNotEmpty(policyInfo.getStatVOList())){
            claimPolicy.setShareRatio(policyInfo.getStatVOList().get(0).getShareRatio());
            claimPolicy.setCededRatio(policyInfo.getStatVOList().get(0).getCededRatio());
            claimPolicy.setNetSelfShare(policyInfo.getStatVOList().get(0).getRetentionRatio());
        }
        if (Objects.equals(Boolean.TRUE, policyInfo.getIsDivideOut())) {
            claimPolicy.setReinsureFlag(YesOrNoEnum.YES.getCode());
        } else {
            claimPolicy.setReinsureFlag(YesOrNoEnum.NO.getCode());
        }
        claimPolicy.setPolicyStartDate(policyInfo.getBusinessInsuranceVO().getStartDate());
        claimPolicy.setPolicyEndDate(policyInfo.getBusinessInsuranceVO().getEndDate());
        claimPolicy.setPolicyYear(policyInfo.getBusinessInsuranceVO().getBusinessYear());
        claimPolicy.setPolicyCurrency(policyInfo.getBusinessInsuranceVO().getCurrency());
        if (Objects.isNull(claimPolicyDO)) {
            claimPolicy.setCreator(user.getNameAndCode());
            claimPolicy.setUpdater(user.getNameAndCode());
            claimPolicyMapper.insert(claimPolicy);
        } else {
            claimPolicy.setId(claimPolicyDO.getId());
            claimPolicy.setUpdateTime(new Date());
            claimPolicy.setUpdater(user.getNameAndCode());
            claimPolicyMapper.updateById(claimPolicy);
        }
    }


    private void saveAttachment(UserEntity user, CgnciClaimCaseAddDTO req, Long caseId) {
        if (CollectionUtils.isEmpty(req.getAccessoryList())) return;
        String uploadNode = ClaimFlowEnum.CLAIM_CASE.getCode();
        Assert.hasText(uploadNode, "uploadNode上传节点必填。");
        List<CgnciAccessoryDO> accessoryList = req.getAccessoryList().stream().map(accessory -> {
            CgnciAccessoryDO accessoryDO = new CgnciAccessoryDO();
            BeanUtils.copyProperties(accessory, accessoryDO);
            accessoryDO.setAccId(null);
            accessoryDO.setBusinessId(caseId);
            accessoryDO.setUploadNode(uploadNode);
            accessoryDO.setBusinessNo(req.getCaseNo());
            accessoryDO.setUpdateUser(user.getNameAndCode());
            accessoryDO.setCreateUser(user.getNameAndCode());
            return accessoryDO;
        }).collect(Collectors.toList());
        accessoryService.deleteByBizNoAndUploadNode(req.getCaseNo(), uploadNode);
        accessoryService.insertList(accessoryList);
    }

    @Override
    public List<ApprovalRecordVO> log(Long caseId) {
        List<CgnciApprovalRecordDO> approvalRecordDOList = approvalRecordMapper.selectList(
                new LambdaQueryWrapper<CgnciApprovalRecordDO>()
                        .eq(CgnciApprovalRecordDO::getFormId, caseId)
        );
        return ConvertUtils.convert(approvalRecordDOList, ApprovalRecordVO.class);
    }

    /**
     * 校验案件是否存在
     */
    private void validateCase(Long caseId) {
        CgnciClaimCaseDO caseInfo = this.getById(caseId);
        if (caseInfo == null) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "案件不存在");
        }
    }


    private CgnciClaimCaseDO getCaseByCaseNo(String caseNo) {
        LambdaQueryWrapper<CgnciClaimCaseDO> param = new LambdaQueryWrapper<CgnciClaimCaseDO>()
                .eq(CgnciClaimCaseDO::getCaseNo, caseNo);
        CgnciClaimCaseDO claimCaseTask = getBaseMapper().selectOne(param);
        return claimCaseTask;
    }

    /**
     * 获取风险信息列表
     */
    private List<CgnciClaimAlertInfoVO> getAlertInfoByCaseNo(String caseNo) {
        List<CgnciClaimAlertInfoDO> alertInfo = claimAlertInfoService.list(
                new LambdaQueryWrapper<CgnciClaimAlertInfoDO>()
                        .eq(CgnciClaimAlertInfoDO::getBusinessNo, caseNo)
                        .orderByDesc(CgnciClaimAlertInfoDO::getAlertId)
        );
        return ConvertUtils.convert(alertInfo, CgnciClaimAlertInfoVO.class);
    }
}